﻿#include<cstdlib>
#include<iostream>
#include<memory>
#include <string>
#include <crtdbg.h>
using namespace std;

class Person
{
public:
	Person(){}
	Person(string iname):mname(iname){}
	virtual ~Person(){}
	virtual void DecoratorShow(){
		cout<< mname <<"had been decorated"<<endl;
	}
	void setName(string iName)
	{
		if (mname !=iName)
		{
			mname = iName;
		}
	}
	string getName()
	{
		return mname;
	}
private:
	string mname;
};

//abstract decorator class
class Finery : public Person
{
public:
	Finery(){}
	~Finery(){
	}
	//用来对对象进行包装，每个装饰的对象的实现和如何使用这个对象分离开了，
	//每个装饰对象只关系自己的功能，不需要关心如何被添加到对象链中
	void SetComponent(Person* ipPerson)
	{
		mPersonPtr = ipPerson;
	}

	void DecoratorShow()
	{
		if (mPersonPtr)
		{
			mPersonPtr->DecoratorShow();
		}
	}
	
	

private:
	//use smart pointer to reference to the target
	Person* mPersonPtr;
};

//concrete decorator class
class Shirt : public Finery
{
public:
	Shirt(const string iShirtName):mShirtName(iShirtName){}
	~Shirt(){}
	void DecoratorShow()
	{
		cout<< mShirtName << "was added"<<endl;
		Finery::DecoratorShow();		
	}
private: 
	string mShirtName;
};

//concrete decorator class
class Suit : public Finery
{
public:
	Suit(const string iSuitName):mSuitName(iSuitName){}
	~Suit(){}
	void DecoratorShow()
	{
		cout<< mSuitName<<"was added"<<endl;
		Finery::DecoratorShow();
	}
private:
	string mSuitName;
};

//concrete decorator class
class Shoes : public Finery
{
public:
	Shoes(const string iShoesName):mShoes(iShoesName){}
	~Shoes(){}
	void DecoratorShow()
	{
		cout<< mShoes <<"was added"<<endl;
		Finery::DecoratorShow();
	}
private: 
	string mShoes;
};

int main()
{
	/*{
		shared_ptr<Shoes> lShoesPtr = make_shared<Shoes>("Shoe") ;
		shared_ptr<Suit> lSuitPtr= make_shared<Suit>("Suite") ;
		shared_ptr<Shirt> lShirtPtr= make_shared<Shirt>("Shirt") ;

		shared_ptr<Person> lPersonPtr = make_shared<Person>("XiaoCai");

		lShoesPtr->SetComponent(lPersonPtr);
		lSuitPtr->SetComponent(lShoesPtr);
		lShirtPtr->SetComponent(lSuitPtr);

		lSuitPtr->DecoratorShow();
		lPersonPtr->DecoratorShow();
	}*/	

	Person lPerson("Xiaocai ");

	Shoes lShoes("Shoe ");
	Suit lSuit("Suit ");
	Shirt lShirt("Shirt ");
	
	lShoes.SetComponent(&lPerson);
	lSuit.SetComponent(&lShoes);
	lShirt.SetComponent(&lSuit);
	
	lShirt.DecoratorShow();
	getchar();
	return 0;
}